home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / screen32.lha / screen-3.2b / window.c < prev   
C/C++ Source or Header  |  1992-02-02  |  14KB  |  602 lines

  1. /* Copyright (c) 1991
  2.  *      Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
  3.  *      Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
  4.  * Copyright (c) 1987 Oliver Laumann
  5.  *
  6.  * This program is free software; you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License as published by
  8.  * the Free Software Foundation; either version 1, or (at your option)
  9.  * any later version.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program (see the file COPYING); if not, write to the
  18.  * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  *
  20.  * Noteworthy contributors to screen's design and implementation:
  21.  *    Wayne Davison (davison@borland.com)
  22.  *    Patrick Wolfe (pat@kai.com, kailand!pat)
  23.  *    Bart Schaefer (schaefer@cse.ogi.edu)
  24.  *    Nathan Glasser (nathan@brokaw.lcs.mit.edu)
  25.  *    Larry W. Virden (lwv27%cas.BITNET@CUNYVM.CUNY.Edu)
  26.  *    Howard Chu (hyc@hanauma.jpl.nasa.gov)
  27.  *    Tim MacKenzie (tym@dibbler.cs.monash.edu.au)
  28.  *    Markku Jarvinen (mta@{cc,cs,ee}.tut.fi)
  29.  *    Marc Boucher (marc@CAM.ORG)
  30.  *
  31.  ****************************************************************
  32.  */
  33.  
  34. #ifndef lint
  35.   static char rcs_id[] = "$Id: window.c,v 1.2 92/02/03 02:28:20 jnweiger Exp $ FAU";
  36. #endif
  37.  
  38. #include <stdio.h>
  39. #include <sys/types.h>
  40. #include <signal.h>
  41. #ifndef sun
  42. #include <sys/ioctl.h>
  43. #endif
  44. #ifdef BSDI
  45. # include <string.h>
  46. #endif /* BSDI */
  47.  
  48. #ifdef ISC
  49. # include <sys/tty.h>
  50. # include <sys/sioctl.h>
  51. # include <sys/pty.h>
  52. #endif
  53.  
  54. #ifdef MIPS
  55. extern int errno;
  56. #endif
  57.  
  58. #include "config.h"
  59. #include "screen.h"
  60. #include "extern.h"
  61.  
  62. static void FreeScrollback __P((struct win *));
  63.  
  64. static int ResizeHistArray __P((struct win *, char ***, int, int, int));
  65. static int ResizeScreenArray __P((struct win *, char ***, int, int, int));
  66. static void FreeArray __P((char ***, int));
  67.  
  68. extern TermcapCOLS, TermcapROWS;
  69. extern int maxwidth;
  70. extern int default_width, default_height, screenwidth, screenheight;
  71. extern char *blank, *null, *OldImage, *OldAttr;
  72. extern char *OldFont, *LastMsg;
  73. extern struct win *wtab[], *fore;
  74. extern int WinList, ForeNum;
  75. extern char *Z0, *Z1, *WS;
  76. extern int Z0width, Z1width;
  77.  
  78. extern int Detached;
  79.  
  80. #if defined(TIOCGWINSZ) || defined(TIOCSWINSZ)
  81.   struct winsize glwz;
  82. #endif
  83.  
  84. /*
  85.  * ChangeFlag:   0: try to modify no window
  86.  *               1: modify fore (and try to modify no other)
  87.  *               2: modify all windows
  88.  *
  89.  * Note: Activate() is only called if change_flag == 1
  90.  *       i.e. on a WINCH event
  91.  */
  92.  
  93. void
  94. CheckScreenSize(change_flag)
  95. int change_flag;
  96. {
  97.   int width, height, n;
  98.   struct win *p;
  99.  
  100.   if (Detached)
  101.     {
  102.       debug("CheckScreenSize: Detached -> No check.\n");
  103.       return;
  104.     }
  105. #ifdef TIOCGWINSZ
  106.   if (ioctl(0, TIOCGWINSZ, &glwz) != 0)
  107.     {
  108.       debug1("CheckScreenSize: ioctl(0, TIOCGWINSZ) errno %d\n", errno);
  109.       width = TermcapCOLS;
  110.       height = TermcapROWS;
  111.     }
  112.   else
  113.     {
  114.       width = glwz.ws_col;
  115.       height = glwz.ws_row;
  116.       if (width == 0)
  117.         width = TermcapCOLS;
  118.       if (height == 0)
  119.         height = TermcapROWS;
  120.     }
  121. #else
  122.   width = TermcapCOLS;
  123.   height = TermcapROWS;
  124. #endif
  125.   
  126.   debug2("CheckScreenSize: screen is (%d,%d)\n", width, height);
  127.  
  128.   if (change_flag == 2)
  129.     {
  130.       for (n = WinList; n != -1; n = p->WinLink)
  131.         {
  132.           p = wtab[n];
  133.           ChangeWindowSize(p, width, height);
  134.     }
  135.     }
  136.   if (screenwidth == width && screenheight == height)
  137.     {
  138.       debug("CheckScreenSize: No change -> return.\n");
  139.       return;
  140.     }
  141.   ChangeScreenSize(width, height, change_flag);
  142.   if (change_flag == 1 && WinList != -1)    /* was HasWindow */
  143.     Activate(fore->norefresh);
  144. }
  145.  
  146. void
  147. ChangeScreenSize(width, height, change_fore)
  148. int width, height;
  149. int change_fore;
  150. {
  151.   struct win *p;
  152.   int n, wwi;
  153.  
  154.   if (screenwidth == width && screenheight == height)
  155.     {
  156.       debug("ChangeScreenSize: no change\n");
  157.       return;
  158.     }
  159.   debug3("ChangeScreenSize to (%d,%d) (change_fore: %d)\n",width, height, change_fore);
  160.   screenwidth = width;
  161.   screenheight = height;
  162.  
  163.   if (WS)
  164.     {
  165.       default_width = TermcapCOLS;
  166.       default_height = TermcapROWS;
  167.     }
  168.   else
  169.     {
  170.       if (Z0 && (width == Z0width || width == Z1width) &&
  171.           (TermcapCOLS == Z0width || TermcapCOLS == Z1width))
  172.         default_width = TermcapCOLS;
  173.       else
  174.         default_width = width;
  175.       default_height = height;
  176.     }
  177.   debug2("Default size: (%d,%d)\n",default_width, default_height);
  178.   if (change_fore)
  179.     {
  180.       if (WinList != -1 && change_fore) /* was HasWindow */
  181.         {
  182.           debug("Trying to change fore.\n");
  183.           ChangeWindowSize(fore, width, height);
  184.         }
  185.     }
  186.   if (WS == NULL)
  187.     {
  188.       /* We have to adapt all windows */
  189.       for (n = WinList; n != -1; n = p->WinLink)
  190.         {
  191.           p = wtab[n];
  192.           debug1("Trying to change window %d.\n",n);
  193.           wwi = width;
  194.           if (Z0 && (width==Z0width || width==Z1width))
  195.         {
  196.           if (p->width > (Z0width + Z1width) / 2)
  197.         wwi = Z0width;
  198.           else
  199.         wwi = Z1width;
  200.         }
  201.           ChangeWindowSize(p, wwi, height);
  202.         }
  203.     }
  204. }
  205.  
  206. int
  207. ChangeScrollback(p, histheight, histwidth)
  208. struct win *p;
  209. int histheight, histwidth;
  210. {
  211.   if (histheight > MAXHISTHEIGHT)
  212.     histheight = MAXHISTHEIGHT;
  213.   debug2("ChangeScrollback(..., %d, %d)\n", histheight, histwidth);
  214.   debug2("  was %d, %d\n", p->histheight, p->width);
  215.  
  216.   if (histheight == 0)
  217.     {
  218.       FreeScrollback(p);
  219.       return 0;
  220.     }
  221.  
  222.   if (ResizeHistArray(p, &p->ihist, histwidth, histheight, 1)
  223.       || ResizeHistArray(p, &p->ahist, histwidth, histheight, 0)
  224.       || ResizeHistArray(p, &p->fhist, histwidth, histheight, 0))
  225.     {
  226.       debug("   failed, removing all histbuf\n");
  227.       FreeScrollback(p);
  228.       Msg_nomem;
  229.       return (-1);
  230.     }
  231.   if (p->histheight != histheight)
  232.     p->histidx = 0;
  233.   p->histheight = histheight;
  234.  
  235.   return(0);
  236. }
  237.  
  238. static void FreeScrollback(p)
  239. struct win *p;
  240. {
  241.   FreeArray(&p->ihist, p->histheight);
  242.   FreeArray(&p->ahist, p->histheight);
  243.   FreeArray(&p->fhist, p->histheight);
  244.   p->histheight = 0;
  245. }
  246.  
  247. static int
  248. ResizeHistArray(p, arr, wi, hi, fillblank)
  249. struct win *p;
  250. char ***arr;
  251. int wi, hi, fillblank;
  252. {
  253.   char **narr, **np, **onp, **onpe;
  254.   int t, x, first;
  255.  
  256.   if (p->width == wi && p->histheight == hi)
  257.     return(0);
  258.   if (p->histheight != hi)
  259.     {
  260.       if ((narr = (char **)calloc(sizeof(char *), hi)) == NULL)
  261.     {
  262.       FreeArray(arr, p->histheight);
  263.       return(-1);
  264.     }
  265.       np = narr;
  266.       onp = (*arr) + p->histidx;
  267.       onpe = (*arr) + p->histheight;
  268.       first = p->histheight - hi;
  269.       if (first<0)
  270.      np-=first;
  271.       for(t=0; t<p->histheight; t++)
  272.     {
  273.           if (t-first >=0 && t-first < hi)
  274.         *np++ = *onp;
  275.       else
  276.         Free(*onp);
  277.       if (++onp == onpe)
  278.         onp = *arr;
  279.     }
  280.       if (*arr)
  281.     Free(*arr);
  282.     }
  283.   else
  284.     narr = *arr;
  285.  
  286.   for (t=0, np=narr; t<hi; t++, np++)
  287.     {
  288.       x = p->width;
  289.       if (*np == 0)
  290.     {
  291.       *np = (char *)malloc(wi);
  292.           x = 0;
  293.     }
  294.       else if (p->width != wi)
  295.     {
  296.       *np = (char *)xrealloc(*np, wi);
  297.     }
  298.       if (*np == 0)
  299.     {
  300.       FreeArray(&narr, hi);
  301.       return(-1);
  302.     }
  303.       if (x<wi)
  304.     {
  305.       if (fillblank)
  306.         bclear(*np+x, wi-x);
  307.       else
  308.         bzero(*np+x, wi-x);
  309.     }
  310.     }
  311.   *arr = narr;
  312.   return(0);
  313. }
  314.       
  315.  
  316. static int
  317. ResizeScreenArray(p, arr, wi, hi, fillblank)
  318. struct win *p;
  319. char ***arr;
  320. int wi, hi, fillblank;
  321. {
  322.   int minr;
  323.   char **cp;
  324.  
  325.   if (p->width == wi && p->height == hi)
  326.     return(0);
  327.  
  328.   if (hi > p->height)
  329.     minr = p->height;
  330.   else
  331.     minr = hi;
  332.  
  333.   if (p->height > hi)
  334.     {
  335.       for (cp = *arr; cp < *arr + (p->height - hi); cp++)
  336.     Free(*cp);
  337.       bcopy((char *)(*arr + (p->height - hi)), (char *)(*arr),
  338.         hi * sizeof(char *));
  339.     }
  340.   if (*arr && p->width != wi)
  341.     for (cp = *arr; cp < *arr + minr; cp++)
  342.       {
  343.     if ((*cp = (char *)xrealloc(*cp, (unsigned) wi)) == 0)
  344.       {
  345.         FreeArray(arr, p->height);
  346.         return(-1);
  347.       }
  348.     if (wi > p->width)
  349.       {
  350.         if (fillblank)
  351.           bclear(*cp + p->width, wi - p->width);
  352.         else
  353.           bzero(*cp + p->width, wi - p->width);
  354.       }
  355.       }
  356.   if (*arr)
  357.     *arr = (char **) xrealloc((char *) *arr, (unsigned) hi * sizeof(char *));
  358.   else
  359.     *arr = (char **) malloc((unsigned) hi * sizeof(char *));
  360.   if (*arr == 0)
  361.     return(-1);
  362.   for (cp = *arr + p->height; cp < *arr + hi; cp++)
  363.     {
  364.       if ((*cp = malloc((unsigned) wi)) == 0)
  365.     {
  366.       while (--cp >= *arr)
  367.         Free(*cp);
  368.       Free(*arr);
  369.           return(-1);
  370.     }
  371.       if (fillblank)
  372.     bclear(*cp, wi);
  373.       else
  374.     bzero(*cp, wi);
  375.     }
  376.   return(0);
  377. }
  378.  
  379. static void
  380. FreeArray(arr, hi)
  381. char ***arr;
  382. int hi;
  383. {
  384.   register char **p;
  385.   register int t;
  386.  
  387.   if (*arr == 0)
  388.     return;
  389.   for (t = hi, p = *arr; t--; p++)
  390.     if (*p)
  391.       Free(*p);
  392.   Free(*arr);
  393. }
  394.  
  395.  
  396. int
  397. ChangeWindowSize(p, width, height)
  398. struct win *p;
  399. int width, height;
  400. {
  401.   int t, scr;
  402.   
  403.   if (width > maxwidth)
  404.     {
  405.       maxwidth = width;
  406.       debug1("New maxwidth: %d\n", maxwidth);
  407.       if (blank == 0)
  408.         blank = malloc((unsigned) maxwidth);
  409.       else
  410.         blank = xrealloc(blank, (unsigned) maxwidth);
  411.       if (null == 0)
  412.         null = malloc((unsigned) maxwidth);
  413.       else
  414.         null = xrealloc(null, (unsigned) maxwidth);
  415.       if (OldImage == 0)
  416.         OldImage = malloc((unsigned) maxwidth);
  417.       else
  418.         OldImage = xrealloc(OldImage, (unsigned) maxwidth);
  419.       if (OldAttr == 0)
  420.         OldAttr = malloc((unsigned) maxwidth);
  421.       else
  422.         OldAttr = xrealloc(OldAttr, (unsigned) maxwidth);
  423.       if (OldFont == 0)
  424.         OldFont = malloc((unsigned) maxwidth);
  425.       else
  426.         OldFont = xrealloc(OldFont, (unsigned) maxwidth);
  427.       if (LastMsg == 0)
  428.         {
  429.           LastMsg = malloc((unsigned) maxwidth + 1);
  430.           *LastMsg = 0;
  431.         }
  432.       else
  433.         LastMsg = xrealloc(LastMsg, (unsigned) maxwidth + 1);
  434.       LastMsg[maxwidth]=0;
  435.       if (!(blank && null && OldImage && OldAttr && OldFont && LastMsg))
  436.     {
  437. nomem:      for (t = WinList; t != -1 && wtab[t] != p; t = p->WinLink) 
  438.         ;
  439.       if (t >= 0)
  440.         KillWindow(t);
  441.       Msg(0, "Out of memory -> Window destroyed !!");
  442.       return(-1);
  443.     }
  444.       MakeBlankLine(blank, maxwidth);
  445.       bzero(null, maxwidth);
  446.     }
  447.   
  448.   if (width == p->width && height == p->height)
  449.     {
  450.       debug("ChangeWindowSize: No change.\n");
  451.       return(0);
  452.     }
  453.  
  454.   debug2("ChangeWindowSize from (%d,%d) to ", p->width, p->height);
  455.   debug2("(%d,%d)\n", width, height);
  456.  
  457.   if (width == 0 && height == 0)
  458.     {
  459.       FreeArray(&p->image, p->height);
  460.       FreeArray(&p->attr, p->height);
  461.       FreeArray(&p->font, p->height);
  462.       if (p->tabs)
  463.     Free(p->tabs);
  464.       p->width = 0;
  465.       p->height = 0;
  466.       FreeScrollback(p);
  467.       return(0);
  468.     }
  469.  
  470.   /* when window gets smaller, scr is the no. of lines we scroll up */
  471.   scr = p->height - height;
  472.   if (scr < 0)
  473.     scr = 0;
  474.   for (t = 0; t < scr; t++)
  475.     AddLineToHist(p, p->image+t, p->attr+t, p->font+t); 
  476.   if (ResizeScreenArray(p, &p->image, width, height, 1)
  477.       || ResizeScreenArray(p, &p->attr, width, height, 0)
  478.       || ResizeScreenArray(p, &p->font, width, height, 0))
  479.     {
  480.       goto nomem;
  481.     }
  482.   /* this won't change the height of the scrollback history buffer, but
  483.    * it will check the width of the lines.
  484.    */
  485.   ChangeScrollback(p, p->histheight, width);
  486.  
  487.   if (p->tabs == 0)
  488.     {
  489.       /* tabs get width+1 because 0 <= x <= width */
  490.       if ((p->tabs = malloc((unsigned) width + 1)) == 0)
  491.         goto nomem;
  492.       t = 8;
  493.     }
  494.   else
  495.     {
  496.       if ((p->tabs = xrealloc(p->tabs, (unsigned) width + 1)) == 0)
  497.         goto nomem;
  498.       t = p->width;
  499.     }
  500.   for (t = (t + 7) & 8; t < width; t += 8)
  501.     p->tabs[t] = 1; 
  502.   p->height = height;
  503.   p->width = width;
  504.   if (p->x >= width)
  505.     p->x = width - 1;
  506.   if ((p->y -= scr) < 0)
  507.     p->y = 0;
  508.   if (p->Saved_x >= width)
  509.     p->Saved_x = width - 1;
  510.   if ((p->Saved_y -= scr) < 0)
  511.     p->Saved_y = 0;
  512.   if (p->autoaka > 0) 
  513.     if ((p->autoaka -= scr) < 1)
  514.       p->autoaka = 1;
  515.   p->top = 0;
  516.   p->bot = height - 1;
  517. #ifdef TIOCSWINSZ
  518.   if (p->ptyfd && p->wpid)
  519.     {
  520.       glwz.ws_col = width;
  521.       glwz.ws_row = height;
  522.       debug("Setting pty winsize.\n");
  523.       if (ioctl(p->ptyfd, TIOCSWINSZ, &glwz))
  524.     debug2("SetPtySize: errno %d (fd:%d)\n", errno, p->ptyfd);
  525. # if defined(STUPIDTIOCSWINSZ) && defined(SIGWINCH)
  526. #  ifdef POSIX
  527.       pgrp = tcgetpgrp(p->ptyfd);
  528. #  else
  529.       if (ioctl(p->ptyfd, TIOCGPGRP, &pgrp))
  530.     pgrp = 0;
  531. #  endif
  532.       if (pgrp)
  533.     {
  534.       debug1("Sending SIGWINCH to pgrp %d.\n", pgrp);
  535.       if (killpg(pgrp, SIGWINCH))
  536.         debug1("killpg: errno %d\n", errno);
  537.     }
  538.       else
  539.     debug1("Could not get pgrp: errno %d\n", errno);
  540. # endif /* STUPIDTIOCSWINSZ */
  541.     }
  542. #endif
  543.   return(0);
  544. }
  545.  
  546.  
  547. void
  548. ResizeScreen(wi)
  549. struct win *wi;
  550. {
  551.   int width, height;
  552.  
  553.   if (wi)
  554.     {
  555.       width = wi->width;
  556.       height = wi->height;
  557.     }
  558.   else
  559.     {
  560.       width = default_width;
  561.       height = default_height;
  562.     }
  563.   if (screenwidth == width && screenheight == height)
  564.     {
  565.       debug("ResizeScreen: No change\n");
  566.       return;
  567.     }
  568.   debug2("ResizeScreen: to (%d,%d).\n", width, height);
  569.   if (WS)
  570.     {
  571.       debug("ResizeScreen: using WS\n");
  572.       WSresize(width, height);
  573.       ChangeScreenSize(width, height, 0);
  574.     }
  575.   else if (Z0 && (width == Z0width || width == Z1width))
  576.     {
  577.       debug("ResizeScreen: using Z0/Z1\n");
  578.       PutStr(width == Z0width ? Z0 : Z1);
  579.       ChangeScreenSize(width, screenheight, 0);
  580.     }
  581.   if (screenwidth != width || screenheight != height)
  582.     {
  583.       debug2("BUG: Cannot resize from (%d,%d)",screenwidth, screenheight);
  584.       debug2(" to (%d,%d) !!\n", width, height);
  585.       if (wi)
  586.     ChangeWindowSize(wi, screenwidth, screenheight);
  587.     }
  588. }
  589.  
  590. char *
  591. xrealloc(mem, len)
  592. char *mem;
  593. int len;
  594. {
  595.   register char *nmem;
  596.  
  597.   if (nmem = realloc(mem, len))
  598.     return(nmem);
  599.   free(mem);
  600.   return((char *)0);
  601. }
  602.